package kr.pe.johnkim.pushchat.mobile.service;

import kr.pe.johnkim.pushchat.mobile.dao.PushChatDiaryDao;
import kr.pe.johnkim.pushchat.mobile.domain.PushChatDiary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.List;

/**
 * @author : John_Kim <cale9797@gmail.com>
 * @date : 13. 7. 11.
 */
@Service
public class PushChatDiaryServiceImpl implements PushChatDiaryService {

    // SLF4J Logging
    private Logger logger = LoggerFactory.getLogger(PushChatDiaryServiceImpl.class);

    @Autowired
    private PushChatDiaryDao pushChatDiaryDao;

    // 생성 할 일기 썸네일 가로 크기.
    private @Value("${diary.thumbnail.width}") int diaryThumbnailWidth;

    // 생성 할 일기 썸네일 세로 크기.
    private @Value("${diary.thumbnail.height}") int diaryThumbnailHeight;

    /**
     * 일기를 등록 한다.
     *
     * @param pushChatDiary
     */
    @Override
    public void registerDiary(PushChatDiary pushChatDiary) {
        logger.error("registerDiary");
        this.pushChatDiaryDao.registerDiary(pushChatDiary);
    }

    /**
     * 일기와 이미지를 등록 한다.
     *
     * @param pushChatDiary
     * @param uploadDiaryImagePath
     * @param uploadDiaryThumbnailPath
     * @param file
     */
    @Override
    public void registerDiaryWithImage(PushChatDiary pushChatDiary, String uploadDiaryImagePath, String uploadDiaryThumbnailPath, MultipartFile file) {
        logger.info("registerDiaryWithImage");

        // 이미지 파일명.
        String fileName = file.getOriginalFilename();

        // 이미지를 업로드 한다.
        try {
            InputStream inputStream = file.getInputStream();
            OutputStream outputStream = new FileOutputStream(uploadDiaryImagePath + fileName);

            int bytesRead;

            byte[] buffer = new byte[8192];

            while((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            outputStream.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 썸네일을 생성 한다.
        try {
            // 썸네일 크기를 설정 한다.
            int width = diaryThumbnailWidth;
            int height = diaryThumbnailHeight;

            // 원본 이미지 파일을 가져 온다.
            File src = new File(uploadDiaryImagePath + fileName);

            BufferedImage bufferedImage = ImageIO.read(src);

            // Aspect Ratio 를 유지하기 위해서 크기를 조정 한다.
            if((float)width/bufferedImage.getWidth() > (float)height/bufferedImage.getHeight()) {
                width = (int)(bufferedImage.getWidth() * ((float)height/bufferedImage.getHeight()));
            } else {
                height = (int)(bufferedImage.getHeight() * ((float)width/bufferedImage.getWidth()));
            }

            BufferedImage thImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

            Graphics2D graphics2D = thImg.createGraphics();
            graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            graphics2D.drawImage(bufferedImage, 0, 0, width, height, null);
            graphics2D.dispose();

            File destinationFile = new File(uploadDiaryThumbnailPath + fileName);
            ImageIO.write(thImg, "png", destinationFile);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 일기를 등록 한다.
        this.pushChatDiaryDao.registerDiary(pushChatDiary);
    }

    /**
     * 일기를 수정 한다.
     *
     * @param pushChatDiary
     */
    @Override
    public void updateDiary(PushChatDiary pushChatDiary) {
        logger.info("updateDiary");
        this.pushChatDiaryDao.updateDiary(pushChatDiary);
    }

    /**
     * 일기와 이미지를 수정 한다.
     *
     * @param pushChatDiary
     * @param uploadDiaryImagePath
     * @param uploadDiaryThumbnailPath
     * @param file
     */
    @Override
    public void updateDiaryWithImage(PushChatDiary pushChatDiary, String uploadDiaryImagePath, String uploadDiaryThumbnailPath, MultipartFile file) {
        logger.info("updateDiaryWithImage");

        // 이미지 파일명.
        String fileName = file.getOriginalFilename();

        // 이미지를 업로드 한다.
        try {
            InputStream inputStream = file.getInputStream();
            OutputStream outputStream = new FileOutputStream(uploadDiaryImagePath + fileName);

            int bytesRead;

            byte[] buffer = new byte[8192];

            while((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            outputStream.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 썸네일을 생성 한다.
        try {
            // 60x60 크기를 기준으로 설정 한다.
            int width = 60;
            int height = 60;

            // 원본 이미지 파일을 가져 온다.
            File src = new File(uploadDiaryImagePath + fileName);

            BufferedImage bufferedImage = ImageIO.read(src);

            // Aspect Ratio 를 유지하기 위해서 크기를 조정 한다.
            if((float)width/bufferedImage.getWidth() > (float)height/bufferedImage.getHeight()) {
                width = (int)(bufferedImage.getWidth() * ((float)height/bufferedImage.getHeight()));
            } else {
                height = (int)(bufferedImage.getHeight() * ((float)width/bufferedImage.getWidth()));
            }

            BufferedImage thImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

            Graphics2D graphics2D = thImg.createGraphics();
            graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            graphics2D.drawImage(bufferedImage, 0, 0, width, height, null);
            graphics2D.dispose();

            File destinationFile = new File(uploadDiaryThumbnailPath + fileName);
            ImageIO.write(thImg, "png", destinationFile);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 일기를 수정 한다.
        this.pushChatDiaryDao.updateDiary(pushChatDiary);
    }

    /**
     * 일기를 비활성화 한다.
     *
     * @param pushChatDiary
     */
    @Override
    public void updateDeactivateDiary(PushChatDiary pushChatDiary) {
        logger.info("updateDeactivateDiary");
        this.pushChatDiaryDao.updateDeactivateDiary(pushChatDiary);
    }

    /**
     * 일기 목록을 가져 온다.
     *
     * @param pushChatDiary
     * @return
     */
    @Override
    public List<PushChatDiary> selectDiaryList(PushChatDiary pushChatDiary) {
        logger.info("selectDiaryList");
        return this.pushChatDiaryDao.selectDiaryList(pushChatDiary);
    }

    /**
     * 일기 상세 정보를 가져 온다.
     *
     * @param pushChatDiary
     * @return
     */
    @Override
    public PushChatDiary selectDiaryInformation(PushChatDiary pushChatDiary) {
        logger.info("selectDiaryInformation");
        return this.pushChatDiaryDao.selectDiaryInformation(pushChatDiary);
    }

    /**
     * 내 일기 목록을 가져 온다.
     *
     * @param pushChatDiary
     * @return
     */
    @Override
    public List<PushChatDiary> selectMyDiaryList(PushChatDiary pushChatDiary) {
        logger.info("selectMyDiaryList");
        return this.pushChatDiaryDao.selectMyDiaryList(pushChatDiary);
    }

    /**
     * 검색한 일기 목록을 가져 온다.
     *
     * @param pushChatDiary
     * @return
     */
    @Override
    public List<PushChatDiary> selectSearchDiaryList(PushChatDiary pushChatDiary) {
        logger.info("selectSearchDiaryList");

        return this.pushChatDiaryDao.selectSearchDiaryList(pushChatDiary);
    }
}
